package com.fruit.service.pay.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.fruit.constants.BillConstant;
import com.fruit.constants.GoodsContant;
import com.fruit.constants.OrderConstant;
import com.fruit.constants.PayConstant;
import com.fruit.mapper.order.OrderMapper;
import com.fruit.mapper.pay.PayMapper;
import com.fruit.pojo.goods.GoodsSpecTime;
import com.fruit.pojo.order.Order;
import com.fruit.pojo.order.OrderConfig;
import com.fruit.pojo.order.OrderGoods;
import com.fruit.pojo.pay.PayInfo;
import com.fruit.pojo.pay.TransactionFlow;
import com.fruit.pojo.user.UserReal;
import com.fruit.sdk.account.AccountManager;
import com.fruit.service.goods.GoodsManager;
import com.fruit.service.order.OrderHandel;
import com.fruit.service.order.OrderManager;
import com.fruit.service.order.impl.OrderLogService;
import com.fruit.service.pay.PayManager;
import com.fruit.service.user.UserManager;
import com.fruit.util.CustomUtil;
import com.fruit.util.DataUtil;
import com.fruit.util.DateUtil;
import com.fruit.util.ResultInfo;
import com.fruit.util.ResultUtil;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class PayService implements PayManager{

	
	@Autowired
	private PayMapper payMapper;
	
	@Autowired
	private OrderMapper orderMapper;
	
	@Autowired
	private OrderManager orderService;
	
	@Autowired
	private OrderHandel orderHandelService;
	
	@Autowired
	private GoodsManager goodsService;
	
	@Autowired
	private OrderLogService orderLogService;
	
	@Autowired
	private AccountManager accountService;
	
	@Autowired
	private UserManager userService;
	
	public Map<String, Object> findCheckOrderParams(PayInfo pi){
		Map<String, Object> resMap = new HashMap<String, Object>();
		try{
		if(pi == null){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "param_error", "参数错误!"));
			return resMap;
		}
		if(pi.getGoodsSpecTimeId() <= 0 || pi.getNum() <= 0 ||pi.getUserId() <= 0){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "param_error", "参数错误!"));
			return resMap;
		}
		//验证金额
		if(pi.getTotalPrice() == null || pi.getTotalPrice().compareTo(BigDecimal.ZERO) <= 0){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "price_error", "支付金额错误!"));
			return resMap;
		}
		//验证用户是否实名
		UserReal userReal = accountService.isReal(pi.getUserId());
		if(userReal == null || !"02".equals(userReal.getState())){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "user_not_real", "用户未实名认证!"));
			return resMap;
		}
		
		//判断商品是否存在
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("id", pi.getGoodsSpecTimeId());
		Map<String, Object> goodsResMap = goodsService.getGoodsSpecTimeById(params);
		ResultInfo ri = (ResultInfo)goodsResMap.get("result");
		if(ResultInfo.ERROR.equals(ri.getState())){
			resMap.put("result", ri);
			return resMap;
		}
		GoodsSpecTime goodsSpecTime = (GoodsSpecTime)goodsResMap.get("gst");
		if(goodsSpecTime == null || GoodsContant.State.DOWN.equals(goodsSpecTime.getState())){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "商品已下架!"));
			return resMap;
		}
		String[] havestTimes = StringUtils.split(goodsSpecTime.getHavestTimes(),"|");
		if(havestTimes == null ||havestTimes.length == 0){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "商品暂不能购买!"));
			return resMap;
		}
		if(GoodsContant.SaleType.YES.equals(goodsSpecTime.getSaleType())){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "商品已售罄!"));
			return resMap;
		}
		goodsSpecTime.setHavestTimes(havestTimes[0]);
		goodsSpecTime.setExpectHarvests(havestTimes[1]);
		//判断金额
		goodsSpecTime.setNum(pi.getNum());
		BigDecimal totalPrice = DataUtil.mul(2, goodsSpecTime.getPrice(),goodsSpecTime.getNum());
		
		if(totalPrice.compareTo(pi.getTotalPrice()) !=0){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "支付金额错误!"));
			return resMap;
		}
		if( pi.getNum() > goodsSpecTime.getMaxShopNum() || pi.getNum()<goodsSpecTime.getMinShopNum()){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "购买数量有误!"));
			return resMap;
		}
		List<OrderConfig> oc = orderMapper.getOrderConfig();
		if(oc == null || oc.size() == 0){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "exception", "系统异常!"));
			return resMap;
		}
		params.clear();
		params.put("userId", pi.getUserId());
		params.put("state", OrderConstant.State.notpay.getValue());
		int orderCnt = orderMapper.getOrderCntByUserId(params);
		if(oc.get(0).getOrderNotpayMaxNum()<= orderCnt){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "请不要重复认养哦!"));
			return resMap;
		}
		
		
		pi.setRemark(goodsSpecTime.getTitle()+"("+pi.getNum()+goodsSpecTime.getUnitDesc()+")");
		pi.setPayPrice(pi.getTotalPrice());
		resMap.put("goodsSpecTime", goodsSpecTime);
		resMap.put("result", ResultUtil.initResult(ResultInfo.SUCCESS, "OK", "校验成功!"));
		return resMap;
		}catch(Exception e){
			e.printStackTrace();
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "exception", "系统异常!"));
			return resMap;
		}
	}
	
	@Override
	public Map<String, Object> saveSubmitOrder(GoodsSpecTime goodsSpecTime,PayInfo pi) {
		Map<String, Object> resMap = new HashMap<String, Object>();
		try{
		//占位
			long curTime = System.currentTimeMillis();
		ResultInfo ri = areaGoodsSeat(goodsSpecTime, pi);
		if(ResultInfo.ERROR.equals(ri.getState())){
			resMap.put("result", ri);
			return resMap;
		}
		pi.getGstList().add(goodsSpecTime);
		//插入账单、交易流水、订单记录、占位
		resMap = saveOrderByGoodsTime(pi);
		String message = "数据响应时间"+(System.currentTimeMillis() - curTime);
		resMap.put("message", message);
		return resMap;
		}catch(Exception e){
			e.printStackTrace();
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "exception", "系统异常!", null, ResultInfo.ROLLBACK));
			return resMap;
		}finally{
			ResultInfo ri = (ResultInfo)resMap.get("result");
			if(ResultInfo.ROLLBACK.equals(ri.getIsRollBack())){
				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			}
		}
	}
	
	public Map<String, Object> saveOrderByGoodsTime(PayInfo pi){
		Map<String, Object> resMap = new HashMap<String, Object>();
		String curTime = DateUtil.getTime();
		TransactionFlow tf = new TransactionFlow();
		tf.setUserId(pi.getUserId());
		tf.setTotalPrice(pi.getTotalPrice());
		tf.setPayPrice(pi.getPayPrice());
		tf.setPriceState(BillConstant.MoneyState.out.getValue());
		tf.setRemark(pi.getRemark());
		tf.setState(PayConstant.State.notpay.getValue());
		tf.setType(BillConstant.Type.consume.getValue());
		tf.setCreateTime(curTime);
		payMapper.saveTransactionFlow(tf);
		tf.setCode(CustomUtil.orderCode(3, tf.getId(), pi.getUserId()));
		int num = payMapper.updateTransactionFlowCode(tf);
		if(num != 1){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "confirm_again", "请重新结算!", null, ResultInfo.ROLLBACK));
			return resMap;
		}
		//插入订单
		Order order = new Order();
		order.setTransactionId(tf.getId());
		order.setUserId(pi.getUserId());
		order.setType(OrderConstant.Type.goods.getValue());
		order.setState(OrderConstant.State.notpay.getValue());
		order.setTotalPrice(pi.getTotalPrice());
		order.setRealPrice(pi.getTotalPrice());
		order.setCreateTime(curTime);
		order.setUpdateTime(curTime);
		payMapper.saveOrder(order);
		order.setCode(CustomUtil.orderCode(3, order.getId(), pi.getUserId()));
		num = payMapper.updateOrderCode(order);
		if(num != 1){
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "confirm_again", "请重新结算!", null, ResultInfo.ROLLBACK));
			return resMap;
		}
		
		//插入订单商品
		for(GoodsSpecTime gst : pi.getGstList()){
			OrderGoods og = new OrderGoods();
			og.setOrderId(order.getId());
			og.setUserId(pi.getUserId());
			og.setBaseId(gst.getBaseId());
			og.setBaseName(gst.getBaseName());
			og.setGoodsTimeId(gst.getGoodsTimeId());
			og.setGoodsSpecTimeId(gst.getId());
			og.setGoodsId(gst.getGoodsId());
			og.setGoodsSpecId(gst.getGoodsSpecId());
			og.setAreaGoodsCountId(gst.getAreaGoodsCountId());
			og.setGoodsSpecCode(gst.getCode());
			og.setClassId(gst.getClassId());
			og.setTitle(gst.getTitle());
			og.setTime(gst.getTime());
			og.setGoodsThumb(gst.getThumbDay());
			og.setThumbDay(gst.getThumbDay());
			og.setThumbNight(gst.getThumbNight());
			og.setPrice(gst.getPrice());
			og.setNumber(gst.getNum());
			og.setUnit(gst.getUnit());
			og.setHarvestUnit(gst.getHarvestUnit());
			og.setSpec(gst.getSpec());
			og.setEndUseTime(gst.getEndUseTime());
			og.setHarvestTimes(gst.getHavestTimes());
			og.setExpectHarvests(gst.getExpectHarvests());
			og.setBirthday(gst.getBirthday());
			og.setFruitPeriod(gst.getFruitPeriod());
			og.setEquityCycle(gst.getEquityCycle());
			og.setAreaGoodsInfoIds(gst.getAreaGoodsInfoIds());
			
			num = payMapper.saveOrderGoods(og);
			if(num != 1){
				resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "confirm_again", "请重新结算!", null, ResultInfo.ROLLBACK));
				return resMap;
			}
		}
		//加入订单取消队列
		orderService.saveAutoCancelOrder(order.getId());
		
		resMap.put("transactionCode", tf.getCode());
		resMap.put("result", ResultUtil.initResult(ResultInfo.SUCCESS, "OK", "保存成功!"));
		
		
		return resMap;
	}

	/**
	 * 区域商品占位
	 * @return
	 * @author admin
	 * @version 2017
	 */
	public ResultInfo areaGoodsSeat(GoodsSpecTime goodsSpecTime,PayInfo pi){
			int num = 0;
			//减去库存
			num = payMapper.updateGoodsSpecTimeStockNum(goodsSpecTime);
			if(num == 0){
				return ResultUtil.initResult(ResultInfo.ERROR, "stock_less", "库存不足!", null, ResultInfo.ROLLBACK);
			}
			
			//修改区域商品统计认购数量
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("id", goodsSpecTime.getAreaGoodsCountId());
			params.put("takeState", "add");
			params.put("takeNum", goodsSpecTime.getNum());
			num = payMapper.updateAreaGoodsTakeNumByMap(params);
			if(num == 0){
				return ResultUtil.initResult(ResultInfo.ERROR, "stock_less", "库存不足!", null, ResultInfo.ROLLBACK);
			}
/*			int number = Integer.parseInt(jedisService.get("num"));
			if(number < goodsSpecTime.getNum()){
				return ResultUtil.initResult(ResultInfo.ERROR, "stock_less", "库存不足!", null, ResultInfo.ROLLBACK);
			}
			jedisService.set("num", number - goodsSpecTime.getNum()+"" );*/
			int m = goodsSpecTime.getNum() % 100;
			int n = goodsSpecTime.getNum() / 100;
			StringBuffer sb = new StringBuffer();
			if(n > 0){
				for(int i=0; i<n; i++){
					params.clear();
					params.put("id", goodsSpecTime.getAreaGoodsCountId());
					params.put("updateNum", 100);
					List<Long> notTakeGoodsIds = payMapper.getNotTakeGoodsIds(params);
					if(notTakeGoodsIds == null || notTakeGoodsIds.size() == 0){
						return ResultUtil.initResult(ResultInfo.ERROR, "stock_less", "库存不足!", null, ResultInfo.ROLLBACK);
					}
					params.clear();
					params.put("isBinding", GoodsContant.Binding.PRE.getValue());
					params.put("userId", pi.getUserId());
					params.put("endUseTime", goodsSpecTime.getEndUseTime());
					params.put("notTakeGoodsIds", notTakeGoodsIds);
					num = payMapper.updateAreaGoodsUserBinding(params);
					if(num != 100){
						return ResultUtil.initResult(ResultInfo.ERROR, "stock_less", "库存不足!", null, ResultInfo.ROLLBACK);
					}
					sb.append(StringUtils.join(notTakeGoodsIds, ",")).append("|");
				}
			}
			if(m > 0){
				params.clear();
				params.put("id", goodsSpecTime.getAreaGoodsCountId());
				params.put("updateNum", m);
				List<Long> notTakeGoodsIds = payMapper.getNotTakeGoodsIds(params);
				if(notTakeGoodsIds == null || notTakeGoodsIds.size() == 0){
					return ResultUtil.initResult(ResultInfo.ERROR, "stock_less", "库存不足!", null, ResultInfo.ROLLBACK);
				}
				params.clear();
				params.put("isBinding", GoodsContant.Binding.PRE.getValue());
				params.put("userId", pi.getUserId());
				params.put("endUseTime", goodsSpecTime.getEndUseTime());
				params.put("notTakeGoodsIds", notTakeGoodsIds);
				num = payMapper.updateAreaGoodsUserBinding(params);
				if(num != m){
					return ResultUtil.initResult(ResultInfo.ERROR, "stock_less", "库存不足!", null, ResultInfo.ROLLBACK);
				}
				sb.append(StringUtils.join(notTakeGoodsIds, ",")).append("|");
			}
			
			if(StringUtils.isEmpty(sb.toString())){
				return ResultUtil.initResult(ResultInfo.ERROR, "stock_less", "库存不足!", null, ResultInfo.ROLLBACK);
			}
			goodsSpecTime.setAreaGoodsInfoIds(sb.substring(0, sb.length()-1));
			return ResultUtil.initResult(ResultInfo.SUCCESS, "OK", "保存成功!");
		
	}
	
	@Override
	public Map<String, Object> updateTransaction(String tradeId, String transactionCode, String payMode) {
		Map<String, Object> resMap = new HashMap<String, Object>();
		TransactionFlow tf = null;
		try{
		log.info("[{}]-【处理订单】-【交易流水号：{}】-【开始】",tradeId,transactionCode);	
		//判断交易流水状态
	    tf = payMapper.getTransactionFlow(transactionCode);
	    if(tf == null){
	    	resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "交易流水不存在!"));
	    	return resMap;
	    }
	    
		if(PayConstant.State.cancel.equals(tf.getState()) 
				||PayConstant.State.pay.equals(tf.getState())){
			//退款流程
			log.info("[{}]-【处理订单】-【退款】-【开始】",tradeId);	
		}else if(PayConstant.State.notpay.equals(tf.getState())){
			//判断业务类型
			if(PayConstant.Type.consume.equals(tf.getType())){
				log.info("[{}]-【处理订单】-【消费订单】-【开始】",tradeId);
				log.info("[{}]-【处理订单】-【消费订单】-【更新交易流水状态】",tradeId);	
				tf.setPayMode(payMode);
				tf.setFinishTime(DateUtil.getTime());
				tf.setState(PayConstant.State.pay.getValue());
				int num = payMapper.updateTransactionFlowState(tf);
				if(num == 0){
					resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "error", "交易流水状态跟更新失败!"));
			    	return resMap;
				}
				log.info("[{}]-【处理订单】-【消费订单】-【更新交易流水状态】-【成功】",tradeId);
				//处理业务订单
				resMap = orderService.updateOrderState(tradeId, tf);
				ResultInfo ri = (ResultInfo) resMap.get("result");
				if(ResultInfo.ERROR.equals(ri.getState())){
					resMap.put("result", ri);
					return resMap;
				}
				//更新用户购买状态
				updateUserBuyState(tradeId, tf);
			}
		}
	    resMap.put("result", ResultUtil.initResult(ResultInfo.SUCCESS, "OK", "处理成功"));
		return resMap;
	    
		}catch(Exception e){
			e.printStackTrace();
			resMap.put("result", ResultUtil.initResult(ResultInfo.ERROR, "exception", "系统异常", null, ResultInfo.ROLLBACK));
			return resMap;
		}finally{
			ResultInfo ri = (ResultInfo)resMap.get("result");
			if(ResultInfo.ROLLBACK.equals(ri.getIsRollBack())){
				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			}
			if(ResultInfo.ERROR.equals(ri.getState())){
				log.error("[{}]-【处理订单】-【异常】-【{}：{}】",tradeId,ri.getCode(),ri.getMessage());
				if(tf != null){
					//插入错误日志
					orderLogService.newSaveExceptionTransaction(tradeId, "PayService", OrderConstant.TransactionServiceState.update.getValue(),
							tf.getCode(), tf.getUserId(), ri.getCode(),ri.getMessage());
				}
			}else{
				log.info("[{}]-【处理订单】-【成功】",tradeId);
			}
			log.info("[{}]-【处理订单】-【结束】",tradeId);
		}
	}

	@Override
	public TransactionFlow getTransactionFlow(String transactionCode) {
		return payMapper.getTransactionFlow(transactionCode);
	}
	
	public void updateUserBuyState(String tradeId,TransactionFlow tf){
		log.info("[{}]-【更新用户购买状态】-【开始】-【用户ID：{}】",tradeId, tf.getUserId());
		try{
			Map<String,Object> resMap = userService.updateUserBuyState(tf.getUserId());
			ResultInfo ri = (ResultInfo) resMap.get("result");
			if(ResultInfo.ERROR.equals(ri.getState())){
				orderLogService.newSaveExceptionTransaction(tradeId, "PayService", OrderConstant.TransactionServiceState.updateUser.getValue(),
						tf.getCode(), tf.getUserId(), "updateUserBuyStateError","更新用户购买状态失败");
			}else{
				log.info("[{}]-【更新用户购买状态】-【成功】",tradeId);
			}
		}catch(Exception e){
			//异常处理
			log.error("[{}]-【更新用户购买状态】-【异常】----{}",tradeId,CustomUtil.getStackTraceAsString(e));
			orderLogService.newSaveExceptionTransaction(tradeId, "PayService", OrderConstant.TransactionServiceState.updateUser.getValue(),
					tf.getCode(), tf.getUserId(), "updateUserBuyStateException","更新用户购买状态异常");
		}
		log.info("[{}]-【更新用户购买状态】-【结束】",tradeId);
	}
	
	
}
